package com.hk.jmm.app.fragment;

import android.Manifest;
import android.graphics.SurfaceTexture;
import android.hardware.usb.UsbDevice;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.TextureView;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.herohan.uvcapp.CameraHelper;
import com.herohan.uvcapp.ICameraHelper;
import com.herohan.uvcapp.ImageCapture;
import com.herohan.uvcapp.VideoCapture;
import com.hjq.permissions.XXPermissions;
import com.hjq.toast.ToastUtils;
import com.hk.jmm.R;
import com.hk.jmm.event.UsbDeviceIn;
import com.hk.jmm.model.AiModel;
import com.hk.jmm.presenter.AiPresenter;
import com.hk.jmm.utils.DeviceCache;
import com.hk.jmm.utils.SaveHelper;
import com.serenegiant.usb.IButtonCallback;
import com.serenegiant.usb.Size;
import com.serenegiant.utils.UriHelper;
import com.serenegiant.widget.AspectRatioSurfaceView;
import com.serenegiant.widget.AspectRatioTextureView;
import com.skyz.base.fragment.BaseMvpFragment;

import java.io.File;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class AiFragment extends BaseMvpFragment<AiModel, AiFragment, AiPresenter> {
    CameraHelper cameraHelper;

    private boolean mIsCameraConnected = false;
    TextView tvVideoRecordTime;
    final int width =1280;
    final int height = 720;


    private AspectRatioSurfaceView viewMainPreview;
    @Override
    public void onMessageEvent(Object event) {
        getMvpPresenter().log("onMessageEvent");
        logTv.append("onMessageEvent\n");
        if(event instanceof UsbDeviceIn){
          UsbDevice device =  DeviceCache.getInstance().getDevice();
          if(device!=null){
              getMvpPresenter().log("onMessageEvent:device=" + device.getDeviceName());
              selectDevice(device);
          }else {
              getMvpPresenter().log("onMessageEvent device =null");
          }
        }
    }

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_home_ai;
    }
    public TextView logTv;
    View layout_none_usb;
    TextView tv_hint;

    boolean isFullScreen = true;
    @Override
    protected void onLayoutInflated(View view) {
        tvVideoRecordTime = view.findViewById(R.id.tvVideoRecordTime);
        tvVideoRecordTime.setVisibility(View.GONE);
        viewMainPreview = view.findViewById(R.id.viewMainPreview);
        layout_none_usb = view.findViewById(R.id.layout_none_usb);
        tv_hint = view.findViewById(R.id.tv_hint);
        logTv = view.findViewById(R.id.tv_log);
        view.findViewById(R.id.click_recording).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //录制
                XXPermissions.with(AiFragment.this)
                        .permission(Manifest.permission.MANAGE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO)
                        .request((permissions, all) -> {
                            toggleVideoRecord(!mIsRecording);
                        });
            }
        });
        view.findViewById(R.id.click_photos).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                XXPermissions.with(AiFragment.this)
                        .permission(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
                        .request((permissions, all) -> {
                            takePicture();
                        });

            }
        });

        view.findViewById(R.id.click_jingpai).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //todo 镜拍
            }
        });
        view.findViewById(R.id.click_full).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 全屏
//                isFullScreen =true;
//                cameraHelper.closeCamera();
//                int width = viewMainPreview.getWidth();
//                int height = viewMainPreview.getHeight();
//                viewMainPreview.setAspectRatio(width, height);
//                final List<UsbDevice> list = cameraHelper.getDeviceList();
//                if (list != null && list.size() > 0) {
//                    cameraHelper.selectDevice(list.get(0));
//                }

            }
        });
        view.findViewById(R.id.click_live).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //todo 推流
            }
        });
        view.findViewById(R.id.click_aisca).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //todo ai识别
            }
        });
        view.findViewById(R.id.click_settings).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //todo 设置
            }
        });

        view.findViewById(R.id.click_todbuy).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //todo 去购买
                if(cameraHelper.getDeviceList()!=null&& cameraHelper.getDeviceList().size()>0){
                    selectDevice( cameraHelper.getDeviceList().get(0));
                }else {
                    ToastUtils.show("去购买");
                }
//
            }
        });

//       viewMainPreview.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
//            @Override
//            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
//                getMvpPresenter().log(new StringBuffer().append("onSurfaceTextureAvailable:").append(width).append(":").append(height).toString());
//                if (cameraHelper != null) {
//                    cameraHelper.addSurface(surface, false);
//                }
//            }
//
//            @Override
//            public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
//                getMvpPresenter().log(new StringBuffer().append("onSurfaceTextureSizeChanged:").append(width).append(":").append(height).toString());
//            }
//
//            @Override
//            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
//                getMvpPresenter().log(new StringBuffer().append("onSurfaceTextureDestroyed").toString());
//                if (cameraHelper != null) {
//                    cameraHelper.removeSurface(surface);
//                }
//                return false;
//            }
//
//            @Override
//            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
//
//            }
//        });

        viewMainPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder holder) {
                getMvpPresenter().log(new StringBuffer().append("onSurfaceTextureAvailable:").append(width).append(":").append(height).toString());
                if (cameraHelper != null) {
                    cameraHelper.addSurface(holder, false);
                }
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
                getMvpPresenter().log(new StringBuffer().append("onSurfaceTextureSizeChanged:").append(width).append(":").append(height).toString());
            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                getMvpPresenter().log(new StringBuffer().append("onSurfaceTextureDestroyed").toString());
                if (cameraHelper != null) {
                    cameraHelper.removeSurface(holder);
                }
            }
        });


    }


    @Override
    protected void initData(Bundle savedInstanceState) {

    }

    private  final Handler handler = new Handler();
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getMvpPresenter().log("onViewCreated:"+width+":"+height);
       handler.postDelayed(new Runnable() {
           @Override
           public void run() {
               int width = viewMainPreview.getWidth();
               int height = viewMainPreview.getHeight();
               viewMainPreview.setAspectRatio(width, height);
           }
       },500);
        checkCameraHelper();
    }



    private void checkCameraHelper() {
        if (!mIsCameraConnected) {
            clearCameraHelper();
        }
        initCameraHelper();
    }

    private void initCameraHelper() {
        getMvpPresenter().log("initCameraHelper"+System.currentTimeMillis());
        if (cameraHelper == null) {
            getMvpPresenter().log("initCameraHelper new CameraHelper");
            cameraHelper = new CameraHelper();
            cameraHelper.setStateCallback(mStateListener);
        }
        setCustomImageCaptureConfig();
        setCustomVideoCaptureConfig();
    }

    @Override
    protected void lazyLoadData(View view) {

    }

    @Override
    protected AiPresenter initMvpPresenter() {
        return new AiPresenter(this, getLifecycle());
    }



    private void selectDevice(final UsbDevice device) {
        mUsbDevice = device;
        getMvpPresenter().log("selectDevice:device=" + device.getDeviceName());
        XXPermissions.with(AiFragment.this)
                .permission(Manifest.permission.CAMERA)
                .request((permissions, all) -> {
                    if (cameraHelper != null) {
                        // 通过UsbDevice对象，尝试获取设备权限
                        getMvpPresenter().log("onPermissionsGranted:device=" + mUsbDevice.getDeviceName());
                        cameraHelper.selectDevice(mUsbDevice);
                    }
                });
    }
    UsbDevice mUsbDevice;
    public void attachNewDevice(UsbDevice device) {
        getMvpPresenter().log("attachNewDevice:device=" + device.getDeviceName());
        if (mUsbDevice == null) {
            selectDevice(device);
        }
    }
    private final ICameraHelper.StateCallback mStateListener = new ICameraHelper.StateCallback() {
        @Override
        public void onAttach(UsbDevice device) {
            getMvpPresenter().log("onAttach:"+device.getDeviceName());
            attachNewDevice(device);
            showHint("正在连接设备");
        }

        @Override
        public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) {
            getMvpPresenter().log("onDeviceOpen:"+device.getDeviceName()+",isFirstOpen:"+isFirstOpen);
            cameraHelper.openCamera();
            cameraHelper.setButtonCallback(new IButtonCallback() {
                @Override
                public void onButton(int button, int state) {
                    getMvpPresenter().log("onButton(button=" + button + "; " +
                            "state=" + state + ")");
                }
            });
            showHint("正在打开设备");
        }

        @Override
        public void onCameraOpen(UsbDevice device) {
            getMvpPresenter().log("onCameraOpen:"+device.getDeviceName());
            showHint("正在打开摄像头");
            cameraHelper.startPreview();
            mIsCameraConnected = true;

            Size size = cameraHelper.getPreviewSize();
            if (size != null) {
//

                if (isFullScreen){
                    int width = viewMainPreview.getWidth();
                    int height = viewMainPreview.getHeight();
                    getMvpPresenter().log("onCameraOpen:"+width+":"+height);
                    viewMainPreview.setAspectRatio(width, height);
                }else {
                    getMvpPresenter().log("onCameraOpen:"+width+":"+height);
                    viewMainPreview.setAspectRatio(width, height);
                }
            }
//            if (viewMainPreview.getSurfaceTexture() != null) {
//                cameraHelper.addSurface(viewMainPreview.getSurfaceTexture(), false);
//            }
            cameraHelper.addSurface(viewMainPreview.getHolder().getSurface(), false);
            updateUIControls();
        }

        @Override
        public void onCameraClose(UsbDevice device) {
            getMvpPresenter().log("onCameraClose:"+device.getDeviceName());
//            if (cameraHelper != null && viewMainPreview.getSurfaceTexture() != null) {
//                cameraHelper.removeSurface(viewMainPreview.getSurfaceTexture());
//            }
            if (cameraHelper != null) {
                cameraHelper.removeSurface(viewMainPreview.getHolder().getSurface());
            }
            if (mIsRecording) {
                toggleVideoRecord(false);
            }
            mIsCameraConnected = false;
            updateUIControls();
            showHint("摄像头已关闭");
        }

        @Override
        public void onDeviceClose(UsbDevice device) {
            getMvpPresenter().log("onDeviceClose:"+device.getDeviceName());
            showHint("设备已关闭");
        }

        @Override
        public void onDetach(UsbDevice device) {
            if (device.equals(mUsbDevice)) {
                mUsbDevice = null;
            }
            getMvpPresenter().log("onDetach:"+device.getDeviceName());
            showHint("设备已拔出");
        }

        @Override
        public void onCancel(UsbDevice device) {
            getMvpPresenter().log("onCancel:"+device.getDeviceName());
            if (device.equals(mUsbDevice)) {
                mUsbDevice = null;
            }
            showHint("设备已取消");
        }
    };


    private void clearCameraHelper() {
        getMvpPresenter().log("clearCameraHelper");
        if (cameraHelper != null) {
            cameraHelper.release();
            cameraHelper = null;
        }
    }
    @Override
    public void onStop() {
        super.onStop();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mIsRecording) {
            toggleVideoRecord(false);
        }
        clearCameraHelper();
        handler.removeCallbacksAndMessages(null);
    }

    private void updateUIControls(){
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                layout_none_usb.setVisibility(mIsCameraConnected?View.GONE:View.VISIBLE);
                viewMainPreview.setVisibility(mIsCameraConnected?View.VISIBLE:View.GONE);
            }
        });

    }

    private void showHint(String msg){
        if(mUsbDevice==null){
            layout_none_usb.setVisibility(View.VISIBLE);
            tv_hint.setText("请将智能眼镜设备插入手机 \n USB-C接口");
        }else {
            layout_none_usb.setVisibility(View.INVISIBLE);
            tv_hint.setText(msg);
        }

    }


    private void setCustomImageCaptureConfig() {
        cameraHelper.setImageCaptureConfig(
                cameraHelper.getImageCaptureConfig().setJpegCompressionQuality(90));
    }
    private void setCustomVideoCaptureConfig() {
        cameraHelper.setVideoCaptureConfig(
                cameraHelper.getVideoCaptureConfig()
//                        .setAudioCaptureEnable(false)
                        .setBitRate((int) (1024 * 1024 * 25 * 0.25))
                        .setVideoFrameRate(25)
                        .setIFrameInterval(1));
    }

    private void startRecord() {
        ToastUtils.show("开始录制视频");
        getMvpPresenter().log("startRecord");
        File file = new File(SaveHelper.getSaveVideoPath());
        VideoCapture.OutputFileOptions options =
                new VideoCapture.OutputFileOptions.Builder(file).build();
        cameraHelper.startRecording(options, new VideoCapture.OnVideoCaptureCallback() {
            @Override
            public void onStart() {
                getMvpPresenter().log("startRecording onStart");
                startRecordTimer();
            }

            @Override
            public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) {
                getMvpPresenter().log("startRecording onVideoSaved:"+UriHelper.getPath(getContext(), outputFileResults.getSavedUri()));
                toggleVideoRecord(false);
            }

            @Override
            public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
                toggleVideoRecord(false);
                getMvpPresenter().log("startRecording onError:videoCaptureError="+videoCaptureError+",message="+message);

            }
        });
    }

    private void stopRecord() {
        ToastUtils.show("停止录制视频");
        getMvpPresenter().log("stopRecord");
        cameraHelper.stopRecording();
    }

    boolean mIsRecording =false;
    public void toggleVideoRecord(boolean isRecording) {
        getMvpPresenter().log("toggleVideoRecord isRecording :"+isRecording);
        try {
            if (isRecording) {
                if (mIsCameraConnected && cameraHelper != null && !cameraHelper.isRecording()) {
                    startRecord();
                }
            } else {
                if (mIsCameraConnected && cameraHelper != null && cameraHelper.isRecording()) {
                    stopRecord();
                }
                stopRecordTimer();
            }
        } catch (Exception e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
            getMvpPresenter().log("toggleVideoRecord Exception :"+e.getLocalizedMessage());
            stopRecordTimer();
        }

        mIsRecording = isRecording;

        updateUIControls();

    }


    private long mRecordStartTime = 0;
    private Timer mRecordTimer = null;
    private static final int QUARTER_SECOND = 250;
    private void startRecordTimer() {
        getMvpPresenter().log("startRecordTimer ");
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvVideoRecordTime.setVisibility(View.VISIBLE);
            }
        });

        // Set “00:00:00” to record time TextView
        setVideoRecordTimeText(formatTime(0));

        // Start Record Timer
        mRecordStartTime = SystemClock.elapsedRealtime();
        mRecordTimer = new Timer();
        //The timer is refreshed every quarter second
        mRecordTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                long recordTime = (SystemClock.elapsedRealtime() - mRecordStartTime) / 1000;
                if (recordTime > 0) {
                    setVideoRecordTimeText(formatTime(recordTime));
                }
            }
        }, QUARTER_SECOND, QUARTER_SECOND);
    }

    private void stopRecordTimer() {
        getMvpPresenter().log("stopRecordTimer ");
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvVideoRecordTime.setVisibility(View.GONE);
            }
        });
        // Stop Record Timer
        mRecordStartTime = 0;
        if (mRecordTimer != null) {
            mRecordTimer.cancel();
            mRecordTimer = null;
        }
        // Set “00:00:00” to record time TextView
        setVideoRecordTimeText(formatTime(0));
    }

    private void setVideoRecordTimeText(String timeText) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvVideoRecordTime.setText(timeText);
            }
        });
    }

    private DecimalFormat mDecimalFormat;
    /**
     * 将秒转化为 HH:mm:ss 的格式
     *
     * @param time 秒
     * @return
     */
    private String formatTime(long time) {
        if (mDecimalFormat == null) {
            mDecimalFormat = new DecimalFormat("00");
        }
        String hh = mDecimalFormat.format(time / 3600);
        String mm = mDecimalFormat.format(time % 3600 / 60);
        String ss = mDecimalFormat.format(time % 60);
        return hh + ":" + mm + ":" + ss;
    }


    public void takePicture() {
        getMvpPresenter().log("takePicture :mIsRecording"+mIsRecording);
        if (mIsRecording) {
            ToastUtils.show("正在录制视频");
            return;
        }

        try {
            File file = new File(SaveHelper.getSavePhotoPath());
            ImageCapture.OutputFileOptions options =
                    new ImageCapture.OutputFileOptions.Builder(file).build();
            cameraHelper.takePicture(options, new ImageCapture.OnImageCaptureCallback() {
                @Override
                public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                    getMvpPresenter().log("takePicture :onImageSaved "+outputFileResults.getSavedUri());
                    ToastUtils.show("拍照成功");
                }

                @Override
                public void onError(int imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
                    getMvpPresenter().log("startRecording onError:imageCaptureError="+imageCaptureError+",message="+message);
                    ToastUtils.show("拍照失败");
                }
            });
        } catch (Exception e) {
            getMvpPresenter().log("startRecording Exception="+e.getLocalizedMessage());
        }
    }

}
